package mincostmaxflow;

import com.Ostermiller.util.CSVParser;
import com.Ostermiller.util.CmdLn;
import com.Ostermiller.util.CmdLnOption;
import com.Ostermiller.util.CmdLnResult;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {

    private static Vector<Edge> initial_graph = new Vector<Edge>();
    private static ArrayList<Integer> source_vertices = new ArrayList<Integer>();
    private static ArrayList<Integer> drain_vertices = new ArrayList<Integer>();
    private static BufferedReader br;

    private enum EnumOptions {
        HELP(new CmdLnOption("help",'?')),
        FILE(new CmdLnOption("file",'f').setRequiredArgument().
                setDescription("file to open"));

        private CmdLnOption option;
        private EnumOptions(CmdLnOption option){
            option.setUserObject(this);
            this.option = option;
        }
        private CmdLnOption getCmdLineOption(){
            return option;
        }
    }

    public static void run() throws Exception{
//        MinCostMaxFlow.launch(initial_graph, source_vertices, drain_vertices);
    }

    public static void readFile(String fName) throws FileNotFoundException, IOException, Exception{
        FileInputStream fis = new FileInputStream(fName);
        CSVParser csvp = new CSVParser(fis);
        csvp.setCommentStart("#@!");

        String[] csv_line;
        while((csv_line = csvp.getLine()) != null){
            if(csv_line[0].contains("Source")){
                for(int i = 1; i < csv_line.length; i++)
                    source_vertices.add(Integer.parseInt(csv_line[i]));
            }
            else if(csv_line[0].contains("Drain")){
                for(int i = 1; i < csv_line.length; i++)
                    drain_vertices.add(Integer.parseInt(csv_line[i]));
            }
            else{
                if(csv_line.length == 4)
                    initial_graph.add(new Edge(
                            //edge start vertice
                            Integer.parseInt(csv_line[0]),
                            //edge end vertice
                            Integer.parseInt(csv_line[1]),
                            //edge cost
                            Integer.parseInt(csv_line[2]),
                            //edge capacity
                            Integer.parseInt(csv_line[3])));
                else
                    throw new IllegalArgumentException("Wrong number of values to create an Edge" +
                            "on line " + csvp.getLastLineNumber() + " of the CSV file!");
            }
        }        
    }

    public static void main(String[] args) throws
            InterruptedException,
            FileNotFoundException,
            IOException,
            Exception {
        CmdLn cmdLn = new CmdLn(args).setDescription("demo command line application");
        for (EnumOptions option: EnumOptions.values()){
            cmdLn.addOption(option.getCmdLineOption());
        }
        String fileName = null;
        for(CmdLnResult result: cmdLn.getResults()){
            switch((EnumOptions)result.getOption().getUserObject()){
                case HELP:{
                    cmdLn.printHelp();
                    System.exit(0);
                } break;
                case FILE:{
                    fileName = result.getArgument();
                } break;
            }
        }

        //initial_graph = new Vector<Edge>();
        //source_vertices = new ArrayList<Integer>();
        //drain_vertices = new ArrayList<Integer>();

        if (fileName != null){
            readFile(fileName);
/*
            FileInputStream fis = new FileInputStream(fileName);
            CSVParser csvp = new CSVParser(fis);
            csvp.setCommentStart("#@!");

            String[] csv_line;
            while((csv_line = csvp.getLine()) != null){
                if(csv_line[0].contains("Source")){
                    for(int i = 1; i < csv_line.length; i++)
                        source_vertices.add(Integer.parseInt(csv_line[i]));
                }
                else if(csv_line[0].contains("Drain")){
                    for(int i = 1; i < csv_line.length; i++)
                        drain_vertices.add(Integer.parseInt(csv_line[i]));
                }
                else{
                    if(csv_line.length == 4)
                        initial_graph.add(new Edge(
                                //edge start vertice
                                Integer.parseInt(csv_line[0]),
                                //edge end vertice
                                Integer.parseInt(csv_line[1]),
                                //edge cost
                                Integer.parseInt(csv_line[2]),
                                //edge capacity
                                Integer.parseInt(csv_line[3])));
                    else
                        throw new IllegalArgumentException("Wrong number of values to create an Edge" +
                                "on line " + csvp.getLastLineNumber() + " of the CSV file!");
                }
            }
            MinCostMaxFlow.launch(initial_graph, source_vertices, drain_vertices);
 */
        }
        else{
            manual_input();
        }
        run();
    }

    public static void manual_input() throws Exception{
        try {
            br = new BufferedReader(new InputStreamReader(System.in));
            System.out.print("Please enter total number of edges: ");
            int edges = Integer.parseInt(br.readLine());
            Edge e;
            int st, dest, cost, capac;

            while (edges > 0){
                System.out.print("Start vertex: ");
                st = Integer.parseInt(br.readLine());
                System.out.print("End vertex: ");
                dest = Integer.parseInt(br.readLine());
                System.out.print("Cost of edge: ");
                cost = Integer.parseInt(br.readLine());
                System.out.print("Capacity of edge: ");
                capac = Integer.parseInt(br.readLine());
                System.out.println();
                e = new Edge(st, dest, cost, capac);
//                if(!initial_graph.contains(e))
                    initial_graph.add(e);
//                else{
//                    initial_graph.add(initial_graph.indexOf(e), e);
//                }

                edges--;
            }

            System.out.print("Please enter total number of start vertices: ");
            int sources = Integer.parseInt(br.readLine());
            while(sources <= 0){
                System.out.print("Please enter total number of start vertices: ");
                sources = Integer.parseInt(br.readLine());
            }
            if(sources == 1){
                System.out.print("Please enter the start vertice: ");
                source_vertices.add(Integer.parseInt(br.readLine()));
            }
            else if (sources > 0){
                while (sources > 0){
                    System.out.print("Please enter the start vertice: ");
                    source_vertices.add(Integer.parseInt(br.readLine()));
                    
                    sources --;
                }
            }

            System.out.print("Please enter total number of end vertices: ");
            int drains = Integer.parseInt(br.readLine());
            while(drains <= 0){
                System.out.print("Please enter total number of end vertices: ");
                drains = Integer.parseInt(br.readLine());
            }
            if(drains == 1){
                System.out.print("Please enter the end vertice: ");
                drain_vertices.add(Integer.parseInt(br.readLine()));
            }
            else if (drains > 0){
                while (drains > 0){
                    System.out.print("Please enter the end vertice: ");
                    drain_vertices.add(Integer.parseInt(br.readLine()));

                    drains --;
                }
            }
//            MinCostMaxFlow.launch(initial_graph, source_vertices, drain_vertices);
        }
        catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
